package com.easonji.admin.service.impl;

import java.util.List;

import javax.annotation.Resource;

import com.easonji.admin.dao.UserDAO;
import com.easonji.admin.manager.DeptManager;
import com.easonji.admin.manager.UserManager;
import com.easonji.admin.mapper.UserAppMapper;
import com.easonji.admin.mapper.UserMapper;
import com.easonji.admin.model.User;
import com.easonji.admin.model.UserApp;
import com.easonji.admin.query.UserQuery;
import com.easonji.admin.service.IPostService;
import com.easonji.admin.service.UserService;
import com.easonji.core.annotion.CacheRemove;
import com.easonji.core.shiro.util.ShiroUtils;
import org.apache.shiro.session.Session;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.easonji.admin.form.UserForm;
import com.easonji.admin.manager.RoleManager;
import com.easonji.admin.mapper.UserRoleMapper;
import com.easonji.admin.model.UserRole;
import com.easonji.common.base.service.AbstractBaseService;
import com.easonji.common.constant.Consts;
import com.easonji.common.constant.cache.CacheConsts;
import com.easonji.common.constant.cache.CacheKeyConsts;
import com.easonji.common.constant.enums.UserSexEnum;
import com.easonji.common.constant.enums.UserStatusEnum;
import com.easonji.common.util.ConvertUtils;
import com.easonji.common.util.DateUtils;
import com.easonji.common.util.JsonUtils;
import com.easonji.common.util.StringUtils;
import com.easonji.core.exception.BizException;

/**
 * @ClassName: UserService
 * @Description: 用户服务实现类
 * @Author: LiuJun
 * @date: 2018/07/30 14:05:38
 * @Version: 1.0
 * @Copyright: Copyright (c) 2018 - 2019
 */
@Service
public class UserServiceImpl extends AbstractBaseService<User> implements UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private UserDAO userDAO;

    @Resource
    private UserRoleMapper userRoleMapper;

    @Resource
    private UserAppMapper userAppMapper;

    @Resource
    private UserManager userManager;

    @Resource
    private DeptManager deptManager;

    @Resource
    private RoleManager roleManager;

    @Resource
    private IPostService iPostService;

    @Override
    public Object queryUserList(UserQuery userQuery) {
        Wrapper<User> wrapper = new EntityWrapper<>();
        wrapper.setSqlSelect("id", "account", "name", "sex", "birthday", "phone_num AS phoneNum", "dept_id AS deptId",
                "status", "gmt_create AS gmtCreate", "gmt_modified AS gmtModified");
        String condition = userQuery.getCondition();
        if (StringUtils.isNotEmpty(condition)) {
            wrapper.like("account", condition).or().like("name", condition).or().like("phone_num", condition);
        }
        Integer status = userQuery.getStatus();
        if (StringUtils.isNotEmpty(status) && status != 0) {
            wrapper.andNew().eq("status", status);
        }
        Integer deptId = userQuery.getDeptId();
        if (StringUtils.isNotEmpty(deptId) && deptId != 0) {
            wrapper.andNew().eq("dept_id", deptId);
            List<Integer> deptIds = deptManager.querySubDeptIdListById(deptId);
            if (StringUtils.isNotEmpty(deptIds)) {
                wrapper.or().in("dept_id", deptIds);
            }
        }
        List<Integer> deptIds = userQuery.getDeptIds();
        if (StringUtils.isNotEmpty(deptIds)) {
            wrapper.andNew().in("dept_id", deptIds);
        }
        // 排序
        wrapper.orderBy("gmt_create");
        List<User> users = userMapper.selectList(wrapper);
        return warp(users);
    }

    @Override
    @Cacheable(value = CacheConsts.CONSTS, key = "'" + CacheKeyConsts.USER_COMBO_LIST + "'")
    public Object queryComboList() {
        Wrapper<User> wrapper = new EntityWrapper<>();
        wrapper.setSqlSelect("id", "name");
        List<User> users = userMapper.selectList(wrapper);
        return users;
    }

    @Override
    public Object queryUser(Integer userId) {
        User user = userMapper.selectById(userId);
        return warp(user);
    }

    @Override
    @CacheRemove(value = CacheConsts.CONSTS, key = { CacheKeyConsts.USER_ACCOUNT, CacheKeyConsts.USER_NAME , CacheKeyConsts.USER_COMBO_LIST})
    public Integer saveUser(UserForm userForm) {
        User user = new User();
        BeanUtils.copyProperties(userForm, user);
        user.setBirthday(DateUtils.convertStrToDate(userForm.getBirthday(), DateUtils.NORM_DATE_PATTERN));
        user.setSalt(ShiroUtils.getRandomSalt(5));
        user.setPassword(ShiroUtils.md5(Consts.DEFAULT_PWD, user.getSalt()));
        user.setStatus(UserStatusEnum.OK.getCode());
        return userMapper.insert(user);
    }

    @Override
    @CacheRemove(value = CacheConsts.CONSTS, key = { CacheKeyConsts.USER_ACCOUNT, CacheKeyConsts.USER_NAME ,CacheKeyConsts.USER_COMBO_LIST})
    public Integer updateUser(UserForm userForm) {
        User user = new User();
        BeanUtils.copyProperties(userForm, user);
        user.setBirthday(DateUtils.convertStrToDate(userForm.getBirthday(), DateUtils.NORM_DATE_PATTERN));
        return userMapper.updateById(user);
    }

    @Override
    public Boolean updateUserStatus(Integer userId, Integer status) {
        User user = new User();
        user.setId(userId);
        user.setStatus(status);
        return user.updateById();
    }

    @Override
    public Boolean checkOldPwd(Integer userId, String oldPwd) {
        boolean result = false;
        User user = userMapper.selectById(userId);
        String oldMd5 = ShiroUtils.md5(oldPwd, user.getSalt());
        if (user.getPassword().equals(oldMd5)) {
            result = true;
        }
        return result;
    }

    @Override
    public Integer updateUserPwd(Integer userId, String pwd) {
        User user = new User();
        user.setId(userId);
        user.setSalt(ShiroUtils.getRandomSalt(5));
        user.setPassword(ShiroUtils.md5(pwd, user.getSalt()));
        return userMapper.updateById(user);
    }

    @Override
    @Transactional(rollbackFor = BizException.class)
    @CacheRemove(value = CacheConsts.CONSTS, key = { CacheKeyConsts.ROLE })
    public Integer updateUserRole(Integer userId, String roleIds) {
        // 删除该用户所有的角色
        Wrapper<UserRole> wrapper = new EntityWrapper<>();
        wrapper.eq("user_id", userId);
        userRoleMapper.delete(wrapper);
        // 添加新的角色
        String[] strIds = ConvertUtils.toStrArray(Consts.COMMA, roleIds);
        for (String id : strIds) {
            UserRole userRole = new UserRole();
            userRole.setUserId(userId);
            userRole.setRoleId(ConvertUtils.toInt(id));
            userRoleMapper.insert(userRole);
        }
        return strIds.length;
    }

    @Override
    @Transactional(rollbackFor = BizException.class)
    @CacheRemove(value = CacheConsts.CONSTS, key = { CacheKeyConsts.APP })
    public Integer updateUserApp(Integer userId, String appIds) {
        // 删除该用户所有的应用
        Wrapper<UserApp> wrapper = new EntityWrapper<>();
        wrapper.eq("user_id", userId);
        userAppMapper.delete(wrapper);
        // 添加新的角色
        String[] strIds = ConvertUtils.toStrArray(Consts.COMMA, appIds);
        for (String id : strIds) {
            UserApp userRole = new UserApp();
            userRole.setUserId(userId);
            userRole.setAppId(ConvertUtils.toInt(id));
            userAppMapper.insert(userRole);
        }
        return strIds.length;
    }

    @Override
    protected JSONObject warp2Json(User user) {
        JSONObject result = JsonUtils.parseObject(user);
        result.put("sexName", UserSexEnum.valueOf(user.getSex()));
        result.put("birthday", DateUtils.convertDateToStr(user.getBirthday(), DateUtils.NORM_DATE_PATTERN));
        result.put("deptName", deptManager.getDeptNameById(user.getDeptId()));
        result.put("statusName", UserStatusEnum.valueOf(user.getStatus()));
        result.put("roleName", userManager.getRoleNameByUserId(user.getId()));
        result.put("appName", userManager.getAppNameByUserId(user.getId()));
        result.put("postName",iPostService.queryRowById(user.getPost()));
        return result;
    }
}
